#include <iostream>

#include <cstdint>
#include <cassert>
#include <cstdio>
#include <cstdlib>

#ifdef __cplusplus
extern "C"
{
#endif
#  include <sys/ipc.h>
#  include <sys/shm.h>
#ifdef __cplusplus
}
#endif
  
#include <robos/shm.hpp>

namespace robos{

    Shm::Shm():Base( ),
               m_key(-1),
               p_memoryStart(NULL),
               p_memoryEnd(NULL),
               m_shmId(-1){}

    Shm::~Shm(){
      shmdt(p_memoryStart);
      shmctl(m_shmId, IPC_RMID, 0);
    }

    key_t Shm::getKey(){
      return this->m_key;
    }

    size_t Shm::getSize(){
      return this->m_size;
    }

    int32_t request(const key_t f_key, const size_t f_size){
      this->m_key = f_key;
      this->m_size = f_size;

      if((this->m_shmId = shmget( this->m_key, 0, 0666)) >= 0){
        shmctl(this->m_shmId, IPC_RMID, 0);
      }

      if((this->m_shmId = shmget(this->m_key, m_size, IPC_CREAT | 0666)) < 0){
      }else{
        void *memoryStart = shmmat(this->m_shmId, NULL, 0);

        if (reinterpret_cast<void*>(-1) == memoryStart){
            err=-2;
        }else{
	    this->p_memoryStart = static_cast<uint8_t*>( memoryStart );
            this->p_memoryEnd   = this->p_memoryStart + this->m_size;
            err=0;
        }
      }

      return 0;
    }
    
    uint8_t* Shm::getMemoryStart(){
      return this->p_memoryStart;
    }
    
    uint8_t* Shm::getMemoryEnd(){
      return this->p_memoryEnd;
    }

    int32_t Shm::getMemoryID(){
      return this->m_shmId;
    }
    
}
